use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::hash::Hash;
use std::ops::Deref;
use std::sync::{Arc, RwLock};

use super::{ID, Plan, Tag};

impl PartialEq for Plan {
    fn eq(&self, other: &Self) -> bool {
        self.gid == other.gid
    }
}
impl PartialOrd for Plan {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.gid.cmp(&other.gid))
    }
}
impl Eq for Plan {}
impl Ord for Plan {
    fn cmp(&self, other: &Self) -> Ordering {
        self.gid.cmp(&other.gid)
    }
}
impl Hash for Plan {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.gid.hash(state);
    }
}
impl Plan {
    pub fn new_root() -> Plan {
        Plan {
            gid: 0,
            parent: None,
            childs: BTreeMap::new(),
            title: "顶级目录".to_string(),
            description: "这里是顶级目录".to_string(),
            tags: vec![],
        }
    }
    pub fn create_empty(parent: &Arc<RwLock<Plan>>, gid: ID) -> Arc<RwLock<Plan>> {
        let child = Plan {
            gid,
            parent: Some(Arc::downgrade(parent)),
            childs: BTreeMap::new(),
            title: "标题".to_string(),
            description: "描述".to_string(),
            tags: vec![Tag::new_beijing_now()],
        };
        let child = Arc::new(RwLock::new(child));
        parent.write().unwrap().childs.insert(gid, child.clone());
        child
    }
    pub fn move_to(this: &Arc<RwLock<Plan>>, new_parent: &Arc<RwLock<Plan>>) -> bool {
        {
            let mut new_parent = new_parent.clone();
            loop {
                if std::ptr::eq(this.deref(), new_parent.deref()) {
                    return false;
                }
                let parent = new_parent.read().unwrap().parent.clone();
                if let Some(parent) = parent {
                    new_parent = parent.upgrade().unwrap();
                } else {
                    break;
                }
            }
        }
        let mut current_plan = this.write().unwrap();
        //移除与旧父节点的关系
        current_plan
            .parent
            .clone()
            .and_then(|weak| weak.upgrade())
            .map(|prev_parent| {
                prev_parent
                    .write()
                    .unwrap()
                    .childs
                    .remove(&current_plan.gid)
            });
        //建立与新父节点的关系
        current_plan.parent = Some(Arc::downgrade(new_parent));
        new_parent
            .write()
            .unwrap()
            .childs
            .insert(current_plan.gid, this.clone());
        true
    }
}
impl Drop for Plan {
    //自己实现的析构函数，把将要析构的节点存进Vec，等以后拿出来一一析构，防止爆栈
    fn drop(&mut self) {
        let mut vec = Vec::new();
        while let Some((_, plan)) = self.childs.pop_last() {
            vec.push(plan);
        }
        while let Some(plan) = vec.pop() {
            let mut plan = plan.write().unwrap();
            while let Some((_, plan)) = plan.childs.pop_last() {
                vec.push(plan);
            }
        }
    }
}
